using System.Diagnostics;
using UnityEngine;
using System.Collections;
using System.Reflection;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Threading;
using UnityEngine;

public class CreateSpriteSheet
{
	static string TexturePackerLicenseKey = "TP-6V42-AJG6-R4AP-PQDH";
    public static string[] bundleDir = new string[]{ResourcesEx.BundleResDir};
	public static string jpgExt = ".jpg";

//	public static void createAllSpriteSheet3(string inputPath, string outputPath, HashSet<string> spriteSheetNames = null)
//	{
//		Directory.CreateDirectory(outputPath);
//		
//		DirectoryInfo dictorys = new DirectoryInfo(inputPath);
//		DirectoryInfo[] childDirs = dictorys.GetDirectories();
//		for(int i = 0; i < childDirs.Length; i++)
//		{
//			string name = childDirs[i].Name;
//
//			if(spriteSheetNames != null)
//			{
//				if(!spriteSheetNames.Contains(name))
//				{
//					continue;
//				}
//			}
//
//			string realOutputPath = outputPath + "/" + name;
//			string outputName = name + ResourcesEx.SpriteSheetTexSuffix;
//
//			string ext = ".png";
//			string[] paths = Directory.GetFiles (inputPath + "/" + name, "*" + jpgExt, SearchOption.AllDirectories);
//			if(paths.Length > 0)
//			{
//				ext = jpgExt;
//			}
//
////			string spriteSheetConfig = inputPath + "/" + name + "/" + MaterialTextureForETC1.spriteSheetConfigName;
////			string str = CommonUtil.fileToString(spriteSheetConfig);
////			SpriteSheetConfig config = JsonConvert.DeserializeObject<SpriteSheetConfig>(str);
//			string trimMode = " --trim-mode CropKeepPos";
////			if(config.ui)
////			{
//////				trimMode = "None";
////			}
//
//			string padding = "";
//			if(ext == jpgExt)
//			{
//				padding = " --border-padding 0";
//				padding += " --extrude 1";
//			}
//			else
//			{
//				padding = " --border-padding 1";
//			}
//			padding += " --shape-padding 1";
//
//			string realSpriteSheetFullPath = realOutputPath + "/" + outputName + ext;
//			File.Delete(realSpriteSheetFullPath);
//
//			string param = string.Format("--force-squared --disable-rotation --format unity-texture2d --data {1}/{3}.tpsheet --sheet {1}/{3}{4} {0}/{2} --max-size {5}{6}{7}", inputPath, realOutputPath, name, outputName, ext, TexAttributeEx.MAX_SIZE, trimMode, padding);
//			CommandLineTool.cmd("/usr/local/bin/TexturePacker", param);
//		}
//	}

//	public static void createAllSpriteSheet2(string inputPath, string outputPath)
//	{
//		if(!Directory.Exists(outputPath))
//		{
//			Directory.CreateDirectory(outputPath);
//		}
//
//		DirectoryInfo dictorys = new DirectoryInfo(inputPath);
//		DirectoryInfo[] childDirs = dictorys.GetDirectories();
//		for(int i = 0; i < childDirs.Length; i++)
//		{
//			string realInputPath = inputPath + "/" + childDirs[i].Name;
//			string realOutputPath = outputPath + "/" + childDirs[i].Name;
//			createAllSpriteSheet3(realInputPath, realOutputPath);
//		}
//	}

//	public static void createAllSpriteSheet4(HashSet<string> spriteSheetNames = null)
//	{
//		if(!File.Exists("/usr/local/bin/TexturePacker"))
//		{
//			return;
//		}
//
//		for(int i = 0; i < TexturePackerImporter.spriteSheetInfos.Length; i++)
//		{
//			SpriteSheetInfo2 info = TexturePackerImporter.spriteSheetInfos[i];
//			createAllSpriteSheet3(info.getSrcPath(), info.getOutputPath(EditorCommonTool.build_target_ios), spriteSheetNames);
//		}
//		
//		AssetDatabase.Refresh();
//	}

	static bool activated = true;
	public static Dictionary<string, Dictionary<string, HashSet<string>>> createAllSpriteSheet5(string resPath, BuildTarget target, HashSet<string> spriteSheetNames = null)
	{
//		if(!File.Exists("/usr/local/bin/TexturePacker"))
//		{
//			return null;
//		}

		if(!activated)
		{
			activated = true;
			bool firstDeactiveate = false;
			if(firstDeactiveate)
			{
				UnityEngine.Debug.LogError("deactivate-license begin");
				while(true)
				{
					int ret = CommandLineTool.Cmd(GetTexturePackerPath(), "--deactivate-license ");
					if(ret == CommandLineTool.ERROR_TIMEOUT)
					{
						UnityEngine.Debug.LogError("deactivate-license again");
						continue;
					}
					
					if(ret != 0)
					{
						UnityEngine.Debug.LogError("deactivate-license error: " + ret);
						return null;
					}

					break;
				}
				UnityEngine.Debug.LogError("deactivate-license finish");
				Thread.Sleep(2000);
			}

			UnityEngine.Debug.LogError("activate-license begin");
			while(true)
			{
				int ret = CommandLineTool.Cmd(GetTexturePackerPath(), "--activate-license " + TexturePackerLicenseKey);
				if(ret == CommandLineTool.ERROR_TIMEOUT)
				{
					UnityEngine.Debug.LogError("activate-license again");
					continue;
				}
				
				if(ret != 0)
				{
					UnityEngine.Debug.LogError("activate-license error: " + ret);
					return null;
				}

				break;
			}

        	UnityEngine.Debug.LogError("activate-license finish");
        }

		Dictionary<string, Dictionary<string, HashSet<string>>> subPackMap = new Dictionary<string, Dictionary<string, HashSet<string>>>();

		SpriteSheetConfig spriteSheetConfig = EditorCommonTool.getSpriteSheetConfig(resPath, target.getPlatform());

		SpriteSheetConfig.Enumerator enumerator = spriteSheetConfig.GetEnumerator();
		while(enumerator.MoveNext())
		{
			Dictionary<string, HashSet<string>> subPacks = createAllSpriteSheet6(spriteSheetConfig, target, resPath, resPath + "/" + EditorCommonTool.getSheetDirName(target), enumerator.Current.Key, enumerator.Current.Value.dirs, enumerator.Current.Value.edge_extrude, enumerator.Current.Value.heuristic_mask, spriteSheetNames);
			if (subPacks != null)
			{
				subPackMap.Add(enumerator.Current.Key, subPacks);
			}
		}

		AssetDatabase.Refresh();

		return subPackMap;
	}

//	public static void copyDirectory(string srcDir, string destDir)
//	{
//		if(!Directory.Exists(srcDir))
//		{
//			return;
//		}
//
//		Directory.CreateDirectory(destDir);
//
//		DirectoryInfo dirInfo = new DirectoryInfo(srcDir);
//		FileInfo[] fileInfos = dirInfo.GetFiles("*", SearchOption.TopDirectoryOnly);
//		for(int i = 0; i < fileInfos.Length; i++)
//		{
//			string filePath = fileInfos[i].FullName;
//			string fileName = Path.GetFileName(filePath);
//			CommonUtil.Copy(filePath, destDir + "/" + fileName);
//		}
//
//		DirectoryInfo[] dirInfos = dirInfo.GetDirectories("*", SearchOption.TopDirectoryOnly);
//		for(int i = 0; i < dirInfos.Length; i++)
//		{
//			string dirPath = dirInfos[i].FullName;
//			string dirName = Path.GetFileName(dirPath);
//			copyDirectory(dirPath, destDir + "/" + dirName);
//		}
//	}

	public static void copyFile(string srcDir, string destDir)
	{
		string dir = Path.GetDirectoryName(destDir);
		Directory.CreateDirectory(dir);
		CommonUtil.Copy(srcDir, destDir);
	}

	public static void copyImageFile(string srcPath, string tempSpriteDir, ref bool isJpg)
	{
		string realSrcPath = srcPath + ".png";
		string realtempSpritePath = tempSpriteDir + ".png";
		isJpg = false;
		if(!File.Exists(realSrcPath))
		{
			isJpg = true;
			realSrcPath = srcPath + ".jpg";
			realtempSpritePath = tempSpriteDir + ".jpg";
		}
		copyFile(realSrcPath, realtempSpritePath);
	}

    public static string GetTexturePackerPath()
    {
        if (Application.platform == RuntimePlatform.OSXEditor)
        {
            return "/usr/local/bin/TexturePacker"; 
        }
        else
        {
            return "d:/Program Files/CodeAndWeb/TexturePacker/bin/TexturePacker.exe";
        }
    }

	public static Dictionary<string, HashSet<string>> createAllSpriteSheet6(SpriteSheetConfig config, BuildTarget target, string inputPath, string outputPath, string spriteSheetName, string[] dirs, int edgeExclude = 0, bool heuristicMask = false, HashSet<string> spriteSheetNames = null)
	{
		if(spriteSheetNames != null)
		{
			if(!spriteSheetNames.Contains(spriteSheetName))
			{
				return null;
			}
		}

		Directory.CreateDirectory(outputPath);

		string forceSquared = "";

		string inputDirPath = "CreateSpriteSheetTempDir";
		string tempOutputDirPath = "OutputSpriteSheetTempDir";



		CommonUtil.Delete(inputDirPath);
		Directory.CreateDirectory(inputDirPath);

		string trimMode = " --trim-mode CropKeepPos";
		string padding = "";

		SpriteSheetInfo info = null;
		if(config != null)
		{
			config.TryGetValue(spriteSheetName, out info);
		}

		string ext = ".png";
		foreach(string dir in dirs)
		{
			string srcPath = inputPath + "/" + dir;
			string tempSpriteDir = inputDirPath + "/" + dir;
			if(Directory.Exists(srcPath))
			{
				CommonUtil.CopyDirectory(srcPath, tempSpriteDir);

				if(ext != jpgExt)
				{
					string[] paths = Directory.GetFiles (srcPath, "*" + jpgExt, SearchOption.AllDirectories);
					if(paths.Length > 0)
					{
						ext = jpgExt;
					}
				}
			}
			else
			{
				bool isJpg = false;
				copyImageFile(srcPath, tempSpriteDir, ref isJpg);
				if(isJpg)
				{
					ext = jpgExt;
				}
			}




			if(padding == "")
			{
				padding = " --border-padding 0";

				if(target == EditorCommonTool.build_target_ios)
				{
					if(info.split_alpha_type != SplitAlphaType.NONE)
					{
						padding = " --border-padding 1";
					}
					else
					{
						forceSquared = "--force-squared ";
					}
				}

				padding += " --extrude " + edgeExclude;

				if(edgeExclude > 0)
				{
					padding += " --shape-padding 0";
				}
				else
				{
					padding += " --shape-padding 1";
				}

				if(heuristicMask)
				{
					padding += " --heuristic-mask";
				}
			}
		}

		string realOutputPath = outputPath + "/" + spriteSheetName;
		string outputName = spriteSheetName + ResourcesEx.SpriteSheetTexSuffix;
		

		
		string realSpriteSheetFullPath = realOutputPath + "/" + outputName + ext;
		CommonUtil.Delete(realSpriteSheetFullPath);


//		string threshold = " --trim-threshold " + (info.alpha_threshold == 0? 20: info.alpha_threshold);
        string threshold = " ";
		padding += threshold;
		string format = "unity-texture2d";
		string dataSuffix = "tpsheet";
		if(info.multi_pack)
		{
			format = "cocos2d-x";
			dataSuffix = "plist";
		}

		int maxSize = TexAttributeEx.MAX_SIZE;
		if(info.max_size > 0)
		{
			maxSize = info.max_size;
			padding += " --multipack";
			outputName += "_{n}";
		}

		if(dataSuffix == "tpsheet")
		{
			tempOutputDirPath = realOutputPath;
		}
		else
		{
			CommonUtil.Delete(tempOutputDirPath);
			Directory.CreateDirectory(tempOutputDirPath);
		}

		float scale = info.getScale();

		string param = string.Format(forceSquared + "--format " + format + " --disable-rotation --algorithm MaxRects --maxrects-heuristics Best --scale " + scale + " --scale-mode Smooth --pack-mode Best --trim-margin 0 --data {1}/{2}." + dataSuffix + " --sheet {1}/{2}{3} {0}/ --max-size {4} {5} {6} --size-constraints POT", inputDirPath, tempOutputDirPath, outputName, ext, maxSize, trimMode, padding);

        string texturePackerPath = GetTexturePackerPath();
		


        string output = null;
        string errorLog = null;
        // CommandLineTool.cmd(texturePackerPath, "--activate-license " + TexturePackerLicenseKey);

        // CommandLineTool.Cmd(GetTexturePackerPath(), "--deactivate-license ");
        // CommandLineTool.Cmd(GetTexturePackerPath(), "--activate-license " + TexturePackerLicenseKey);

        int exitCode = CommandLineTool.CmdWithOutput(texturePackerPath, param, ref output, ref errorLog);

        if (exitCode != 0)
		{
			throw new System.Exception(errorLog);
		}

		UnityEngine.Debug.Log(param);
		

		Dictionary<string, HashSet<string>> subPacks = null;
		if(dataSuffix != "tpsheet")
		{
			string[] files = Directory.GetFiles(tempOutputDirPath, "*" + ext, SearchOption.AllDirectories);
			if (files.Length <= 0)
			{
                throw new System.Exception("create sprite sheet failed by cmd: " + param);
			}
			else if(files.Length <= 1)
			{
				string filePath = files[0];
				int index = filePath.LastIndexOf("_0");
				string newFilePath = filePath.Remove(index, 2);
				newFilePath = newFilePath.Replace(tempOutputDirPath, realOutputPath);
				Directory.CreateDirectory(realOutputPath);
				CommonUtil.Delete(newFilePath);
				CommonUtil.Move(filePath, newFilePath);
				filePath = filePath.Replace(ext, ".plist");
				newFilePath = newFilePath.Replace(ext, ".plist");
				CommonUtil.Delete(newFilePath);
				CommonUtil.Move(filePath, newFilePath);

				subPacks = new Dictionary<string, HashSet<string>>();
				for(int i = 0; i < 20; i++)
				{
					string dir = Path.GetDirectoryName(newFilePath);
					dir += "_" + i;
					CommonUtil.Delete(dir);
				}
			}
			else
			{
				subPacks = new Dictionary<string, HashSet<string>>();
				int i = 0;
				for(; i < files.Length; i++)
				{
					CommonUtil.Delete(realOutputPath);
					string filePath = files[i];
					string dirPath = Path.GetDirectoryName(realOutputPath);
					string newSpName = Path.GetFileNameWithoutExtension(filePath);
					string realDir = dirPath + "/" + newSpName;
					Directory.CreateDirectory(realDir);
					string newFilePath = filePath.Replace(tempOutputDirPath, realDir);
					CommonUtil.Delete(newFilePath);
					CommonUtil.Move(filePath, newFilePath);
					filePath = filePath.Replace(ext, ".plist");
					newFilePath = newFilePath.Replace(ext, ".plist");
					CommonUtil.Delete(newFilePath);
					CommonUtil.Move(filePath, newFilePath);

					HashSet<string> pathSet = MaterialTextureForETC1.getSpriteSheetSpritePaths(newFilePath);

					subPacks.Add(newSpName, pathSet);
				}

				for(; i < 20; i++)
				{
					string filePath = files[0];
					string dirPath = Path.GetDirectoryName(realOutputPath);
					string newSpName = Path.GetFileNameWithoutExtension(filePath);
					string realDir = dirPath + "/" + newSpName;

					int index = realDir.LastIndexOf("_0");
					string dir = realDir.Remove(index, 2);
					dir = dir.Insert(index, "_" + i);
                    CommonUtil.Delete(dir);
                }
			}

			CommonUtil.Delete(tempOutputDirPath);
		}

        CommonUtil.Delete(inputDirPath);

		return subPacks;
	}
}